package client.backend.price;

import java.util.LinkedList;
import java.util.StringTokenizer;
import java.lang.Math;

import client.backend.Connection;
import server.conn.ConnectionThread;
import server.conn.user.UserConnectionThread;

/**
 * Stores data related to the ratio between two currencies.
 *
 */
public class Price {
	private String cur1;
	private String cur2;
	private float buy;
	private float sell;
	private long time;
	private static String[] currencies;
	
	private boolean canUpdate;
	
	/**
	 * Creates a new price object for two currencies.
	 * @param cur1	First currency.
	 * @param cur2	Second currency.
	 */
	public Price(String cur1, String cur2) {
		this.cur1 = cur1;
		this.cur2 = cur2;
		canUpdate = true;
	}
	
	/**
	 * Private method for creating new price objects with ratio and time.
	 * @param cur1	First currency.
	 * @param cur2	Second currency.
	 * @param rate	rate.
	 * @param time	time created.
	 */
	private Price(String cur1, String cur2, float rate, long time) {
		this.cur1 = cur1;
		this.cur2 = cur2;
		this.buy = this.sell = rate;
		this.time = time;
		canUpdate = false;
	}
	
	/**
	 * update current price of this object.
	 * @param buy	buy price.
	 * @param sell	sell price.
	 * @param time	timestamp.
	 */
	protected void updatePrice(float buy, float sell, long time) {
		updatePrice(buy, sell, time, true);
	}
	
	/**
	 * Updates the information in this object.
	 * @param buy		Buy price.
	 * @param sell		Sell price.
	 * @param time		timestamp.
	 * @param doInverse	boolean to do inverse of price.
	 */
	private void updatePrice(float buy, float sell, long time, boolean doInverse) {
		if (canUpdate) {
			this.buy = buy;
			this.sell = sell;
			this.time = time;
			if (doInverse)
				updateInverse();
		}
	}
	
	/**
	 * Private method to set inverse prices.
	 */
	private void updateInverse() {
		float newBuy = 1/sell;
		float newSell = 1/buy;
		
		PriceController.getInstance().getPrice(cur2, cur1).updatePrice(newBuy, newSell, time, false);
	}
	
	/**
	 * Returns LinkedList of history of orders using this currency pair.
	 * @param limit	Max length of history.
	 * @param bType	Buy or Sell.
	 * @return		LinkedList of Price(s) of history.
	 */
	public LinkedList<Price> getHistory(int limit, int bType) {
		if (canUpdate) {
			int action = UserConnectionThread.PRICE_GET_HISTORY;
			String split = ConnectionThread.SPLIT;
			
			String[] history = Connection.getInstance().readArray(action+split+cur1+split+cur2+split+limit+split+bType);
			
			LinkedList<Price> historyList = new LinkedList<Price>();
			
			for (String price : history) {
				StringTokenizer strTok = new StringTokenizer(price, split);
				
				historyList.add(new Price(cur1, cur2, new Float(strTok.nextToken()), new Long(strTok.nextToken())));
			}
			
			return historyList;
		} else {
			return null;
		}
	}
	
	/**
	 * Static method to separate a currency pair into 2 strings.
	 * @param currPair	Currency pair to be separated.
	 * @return	Array two long of currencies.
	 */
	public static String[] seperateCurrencies(String currPair) {
		String response[] = new String[2];
		response[0] = currPair.substring(0,3);
		response[1] = currPair.substring(3,6);
		return response;
	}
	
	public String toString() { 
		float tempBuy = roundFloat(buy);
		float tempSell = roundFloat(sell);
		return "<html>B: "+tempBuy+"<br>S: "+tempSell+"</html>";
	}
	
	public static float roundFloat(float d) {
        float temp = Math.round(d * 10000);
		return temp/10000;
    }
	
	/**
	 * Getter method for buy price.
	 * @return	Buy price.
	 */
	public float getBuy() { return buy; }
	
	/**
	 * Getter method for sell.
	 * @return	Sell price.
	 */
	public float getSell() { return sell; }
	
	/**
	 * Getter method for time.
	 * @return	Time.
	 */
	public long getTime() { return time; }
	
	/**
	 * Getter method for first currency.
	 * @return	First currency.
	 */
	public String getCur1() { return cur1; }
	
	/**
	 * Getter method for curreny 
	 * @return	Second currency.
	 */
	public String getCur2() { return cur2; }
	
}
